// Copyright (c) Runtime Verification, Inc. All Rights Reserved.
package org.kframework.utils.inject;

import static org.fusesource.jansi.internal.CLibrary.*;

import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
import java.io.File;
import java.util.Map;
import org.kframework.main.GlobalOptions;
import org.kframework.main.Tool;
import org.kframework.utils.file.Environment;
import org.kframework.utils.file.FileUtil;
import org.kframework.utils.file.TTYInfo;
import org.kframework.utils.file.TempDir;
import org.kframework.utils.file.WorkingDir;

public class CommonModule extends AbstractModule {

  @Override
  protected void configure() {
    binder().requireAtInjectOnConstructors();
    SimpleScope requestScope = new SimpleScope();
    bindScope(RequestScoped.class, requestScope);
    DefinitionScope definitionScope = new DefinitionScope();
    bindScope(DefinitionScoped.class, definitionScope);
    bind(SimpleScope.class).annotatedWith(Names.named("requestScope")).toInstance(requestScope);
    bind(DefinitionScope.class).toInstance(definitionScope);
    bind(File.class)
        .annotatedWith(WorkingDir.class)
        .toProvider(SimpleScope.seededKeyProvider())
        .in(RequestScoped.class);
    bind(new TypeLiteral<Map<String, String>>() {})
        .annotatedWith(Environment.class)
        .toProvider(SimpleScope.seededKeyProvider())
        .in(RequestScoped.class);
    bind(Long.class)
        .annotatedWith(StartTime.class)
        .toProvider(SimpleScope.seededKeyProvider())
        .in(RequestScoped.class);
  }

  @Provides
  @TempDir
  @RequestScoped
  File tempDir(Tool tool, GlobalOptions go) {
    if (go.tempDir != null)
      return new File(
          go.tempDir, FileUtil.generateUniqueFolderName("." + tool.name().toLowerCase()));
    return new File(
        System.getProperty("java.io.tmpdir"),
        FileUtil.generateUniqueFolderName("." + tool.name().toLowerCase()));
  }

  @Provides
  ProcessBuilder pb(@WorkingDir File workingDir, @Environment Map<String, String> env) {
    return new FileUtil(null, workingDir, null, null, env).getProcessBuilder();
  }

  @Provides
  @RequestScoped
  TTYInfo ttyInfo(@Environment Map<String, String> env) {
    boolean stdin, stdout, stderr;
    if (env.containsKey("NAILGUN_TTY_0")) {
      stdin = !env.get("NAILGUN_TTY_0").equals("0");
    } else {
      stdin = isatty(0) != 0;
    }
    if (env.containsKey("NAILGUN_TTY_1")) {
      stdout = !env.get("NAILGUN_TTY_1").equals("0");
    } else {
      stdout = isatty(1) != 0;
    }
    if (env.containsKey("NAILGUN_TTY_2")) {
      stderr = !env.get("NAILGUN_TTY_2").equals("0");
    } else {
      stderr = isatty(2) != 0;
    }
    return new TTYInfo(stdin, stdout, stderr);
  }
}
